using System;
using System.Collections.Generic;
using OracleInternal.Common;
using OracleInternal.Secure.Network;

namespace OracleInternal.Network
{
	internal class DataIntegrityService : AnoService
	{
		private static readonly string[] DATAINTEGRITY_ANO_ID = new string[6]
		{
			"",
			"MD5",
			"SHA1",
			"SHA512",
			"SHA256",
			"SHA384"
		};

		private static readonly byte[] DATAINTEGRITY_ORACLE_ID = new byte[6]
		{
			0,
			1,
			3,
			4,
			5,
			6
		};

		private int m_resp;

		private int i;

		private bool checkSummingActivated;

		private byte[] clientPK;

		internal DataIntegrityService()
		{
		}

		internal override int Initialize(SessionContext sessCtx)
		{
			ConnectionOption conops = sessCtx.m_conops;
			SqlNetOraConfig sNOConfig = conops.SNOConfig;
			string level = ((conops.CryptoChecksum != null) ? conops.CryptoChecksum : sNOConfig["sqlnet.crypto_checksum_client"]);
			string value = ((conops.CryptoChecksumTypes != null) ? conops.CryptoChecksumTypes : sNOConfig["sqlnet.crypto_checksum_types_client"]);
			base.Initialize(sessCtx);
			m_service = 3;
			m_level = AnoService.translateAnoValue(level);
			if (m_level == -1)
			{
				throw new NetworkException(-6322);
			}
			string[] userList = SqlNetOraConfig.MultipleValueSplit(value);
			userList = AnoService.ValidateUserChoiceDrivers(userList, DATAINTEGRITY_ANO_ID);
			if (userList == null)
			{
				return 0;
			}
			m_userChoiceDriversId = new List<int>(userList.Length);
			for (i = 0; i < userList.Length; i++)
			{
				m_userChoiceDriversId.Add(GetDriverID(DATAINTEGRITY_ANO_ID, userList[i]));
			}
			createDriversListWithLevel(ref m_userChoiceDriversId, m_level);
			m_selectedDrivers = new byte[m_userChoiceDriversId.Count];
			for (i = 0; i < m_selectedDrivers.Length; i++)
			{
				m_selectedDrivers[i] = DATAINTEGRITY_ORACLE_ID[m_userChoiceDriversId[i]];
			}
			int num = 1;
			if (m_userChoiceDriversId.Count == 0)
			{
				if (m_level == 3)
				{
					throw new NetworkException(-6322);
				}
				num |= 8;
			}
			else if (m_level == 3)
			{
				num |= 0x10;
			}
			return num;
		}

		internal override int GetServiceDataLength()
		{
			return 12 + m_selectedDrivers.Length;
		}

		internal override void ReceiveServiceData(int numSubPackets)
		{
			m_version = m_anoComm.ReceiveVersion();
			int num = m_anoComm.ReceiveUB1();
			m_algID = -1;
			for (int i = 0; i < DATAINTEGRITY_ANO_ID.Length; i++)
			{
				if (DATAINTEGRITY_ORACLE_ID[i] == num)
				{
					m_algID = i;
				}
			}
			checkSummingActivated = ((m_algID > 0) ? true : false);
			if (numSubPackets == 8)
			{
				ushort num2 = (ushort)m_anoComm.ReceiveUB2();
				ushort num3 = (ushort)m_anoComm.ReceiveUB2();
				byte[] a_ = m_anoComm.ReceiveRaw();
				byte[] array = m_anoComm.ReceiveRaw();
				byte[] array2 = m_anoComm.ReceiveRaw();
				byte[] initializationVector = m_anoComm.ReceiveRaw();
				if (num2 <= 0 || num3 <= 0)
				{
					throw new Exception("Bad parameters from server");
				}
				int num4 = (num3 + 7) / 8;
				if (array2.Length != num4 || array.Length != num4)
				{
					throw new Exception("DiffieHellman negotiation out of synch");
				}
				DiffieHellman diffieHellman = new DiffieHellman(a_, array, num2, num3);
				clientPK = diffieHellman.getPublicKey();
				m_sessCtx.m_ano.setClientPK(clientPK);
				m_sessCtx.m_ano.setInitializationVector(initializationVector);
				m_sessCtx.m_ano.setSessionKey(diffieHellman.getSessionKey(array2, array2.Length));
			}
		}

		internal override void ActivateAlgorithm()
		{
			Ano ano = m_sessCtx.m_ano;
			if (!checkSummingActivated)
			{
				return;
			}
			if (DATAINTEGRITY_ANO_ID[m_algID].Equals("MD5", StringComparison.InvariantCultureIgnoreCase))
			{
				try
				{
					ano.dataIntegrityAlg = new MD5();
				}
				catch (Exception inner)
				{
					throw new NetworkException(12649, inner);
				}
			}
			else if (DATAINTEGRITY_ANO_ID[m_algID].Equals("SHA1", StringComparison.InvariantCultureIgnoreCase))
			{
				try
				{
					ano.dataIntegrityAlg = new SHA1();
				}
				catch (Exception inner2)
				{
					throw new NetworkException(12649, inner2);
				}
			}
			else if (DATAINTEGRITY_ANO_ID[m_algID].Equals("SHA256", StringComparison.InvariantCultureIgnoreCase))
			{
				try
				{
					ano.dataIntegrityAlg = new SHA256();
				}
				catch (Exception inner3)
				{
					throw new NetworkException(12649, inner3);
				}
			}
			else if (DATAINTEGRITY_ANO_ID[m_algID].Equals("SHA384", StringComparison.InvariantCultureIgnoreCase))
			{
				try
				{
					ano.dataIntegrityAlg = new SHA384();
				}
				catch (Exception inner4)
				{
					throw new NetworkException(12649, inner4);
				}
			}
			else
			{
				if (!DATAINTEGRITY_ANO_ID[m_algID].Equals("SHA512", StringComparison.InvariantCultureIgnoreCase))
				{
					throw new NetworkException(12649);
				}
				try
				{
					ano.dataIntegrityAlg = new SHA512();
				}
				catch (Exception inner5)
				{
					throw new NetworkException(12649, inner5);
				}
			}
			ano.dataIntegrityAlg.init(ano.getSessionKey(), ano.getInitializationVector(), DATAINTEGRITY_ANO_ID[m_algID]);
			m_sessCtx.cryptoNeeded = true;
		}

		internal override void ValidateResponse()
		{
		}
	}
}
